using System;
using System.Collections.Generic;
using CLELCore.Assembly.StreamTables;
using CLELCore.Assembly.BlobStreams.BlobInfo;
using CLELCore.Assembly.CLELInstructions;
using CLELCore.Assembly.MethodHeaderDataSections;
using CLELCore.Assembly.MethodHeaderDataSections.MethodHeaderDataSectionRows;
using CLELCore.Assembly.Descriptors.ClassDescriptors;

namespace CLELCore.Assembly.Descriptors
{
	public class MethodDescriptor
	{
		private CLELAssembly _assembly;
		private Token _token;

		public Token MethodToken
		{
			get
			{
				return _token.Copy();
			}
		}

		public List<CLELInstruction> GetMethodsCode()
		{
			if(_assembly == null)
				throw new AssemblyDisposedException("Assembly has been disposed and set to null");
			return _assembly.GetCodeForMethod(_token);
		}
		
		public void SetMethodsCode(List<CLELInstruction> code,MethodLocalsBlobInfo locals)
		{
			if(_assembly == null)
				throw new AssemblyDisposedException("Assembly has been disposed and set to null");
			_assembly.SetMethodsCode(this,code,locals);
		}

		public MethodLocalsBlobInfo Locals
		{
			get
			{
				if(_assembly == null)
					throw new AssemblyDisposedException("Assembly has been disposed and set to null");
				return _assembly.GetMethodsLocals(_token);
			}
		}

		public List<ParameterDescriptor> Parameters
		{
			get
			{
				if(_assembly == null)
					throw new AssemblyDisposedException("Assembly has been disposed and set to null");
				MethodBlobInfo info =  _assembly.GetMethodBlobInfo(_token);
				if(info != null)
					return info.Parameters;
				return null;
			}
		}

		public MethodHeaderDataSection SEHDataSection
		{
			get
			{
				if(_assembly == null)
					throw new AssemblyDisposedException("Assembly has been disposed and set to null");
				return _assembly.GetMethodsSEHDataSection(_token);
			}
			set
			{
				if(_assembly == null)
					throw new AssemblyDisposedException("Assembly has been disposed and set to null");
				_assembly.SetMethodsSEHDataSection(_token,value);
			}
		}

		public bool IsStatic
		{
			get
			{
				short flags = _assembly.GetMethodFlags(_token);
				return ((flags & MethodFlags.STATIC) == MethodFlags.STATIC);
			}
		}

		public MethodDescriptor(CLELAssembly assembly,Token token)
		{
			if(assembly == null)
				throw new ArgumentException("CLEL assembly cannot be null");
			if(token == null)
				throw new ArgumentException("Method token cannot be null");
			_assembly = assembly;
			_token = token;
		}
	}
}
